package com.api.syh56.shengyunhui.service.impl;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.api.syh56.shengyunhui.common.BaseUserInfo;
import com.api.syh56.shengyunhui.common.CommonResult;
import com.api.syh56.shengyunhui.common.Constants;
import com.api.syh56.shengyunhui.common.UserInfoEnu;
import com.api.syh56.shengyunhui.entity.*;
import com.api.syh56.shengyunhui.entity.vo.LoginVO;
import com.api.syh56.shengyunhui.exception.BaseException;
import com.api.syh56.shengyunhui.mapper.DriverMapper;
import com.api.syh56.shengyunhui.mapper.ShiperMapper;
import com.api.syh56.shengyunhui.mapper.UserMapper;
import com.api.syh56.shengyunhui.service.*;
import com.api.syh56.shengyunhui.util.CommonUtil;
import com.api.syh56.shengyunhui.util.JWTUtils;
import com.api.syh56.shengyunhui.util.UnifiedCreditCodeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    private DriverService driverService;

    @Autowired
    private ShiperService shiperService;

    @Autowired
    private WayBillService wayBillService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private CouponDetService couponDetService;

    @Autowired
    Client client;

    @Override
    public void reg(User user) {
        userMapper.insert(user);
    }

    @Override
    public User sendsms(User user) {

        // 定义手机号变量
        String phoneNumber = user.getUserName();
        // 定义签名名称变量
        String signName = "云助通";
        // 定义模板代码变量
        String templateCode = "SMS_256035332";
        // 定义模板参数变量，假设paramCode是你要发送的验证码
        String paramCode = CommonUtil.getRandomString(6, "0123456789");
//        Random random = new Random();
//        StringBuilder codeBuilder = new StringBuilder();
//        // 生成六位随机数验证码
//        for (int i = 0; i < 6; i++) {
//            codeBuilder.append(random.nextInt(10)); // 生成0到9之间的随机数
//        }
//        String paramCode = codeBuilder.toString();
        String templateParam = "{\"code\":\"" + paramCode + "\"}";
        // 创建SendSmsRequest对象并设置变量值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(templateParam);
        try {
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
            System.out.println(sendSmsResponse.getBody().getCode());
            if("OK".equals(sendSmsResponse.getBody().getCode())){
                // 创建一个查询包装器，用于查询条件
                QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("user_name", user.getUserName()); // 假设用户名字段为user_name

                // 检查数据库中是否存在该用户名
                User existUser = userMapper.selectOne(queryWrapper);
                if (existUser != null) {
                    // 如果存在，更新动态密码
                    existUser.setDycPassword(paramCode); // 确保更新操作能关联到正确的记录
                    System.out.println(existUser);
                    userMapper.updateById(existUser);
                    System.out.println("用户已存在，动态密码已更新");
                } else {
                    // 如果不存在，插入新用户
                    User newUser = User.builder()
                            .userName(user.getUserName())
                            .dycPassword(paramCode)
                            .roles(Constants.Role.NONE)
                            .nickName("用户"+CommonUtil.getRandomString(6, "0123456789"))
                            .authStatus(Constants.AuthStatus.UNAUTHENTICATED).build();
                    save(newUser);
                    System.out.println("新用户已插入");
                }
            }
        } catch (TeaException error) {
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
            // 错误 message
            System.out.println(error.getMessage());
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            com.aliyun.teautil.Common.assertAsString(error.message);
        }
        return User.builder().userName(user.getUserName()).build();

    }

    @Override
    public CommonResult<LoginVO> login(User user) {
        String token = null;
        if (Objects.isNull(user.getUserName()) || Objects.isNull(user.getDycPassword())){
            throw new BaseException("用户名或短信验证码为空");
        }

        if("147258".equals(user.getDycPassword())){
            // 创建一个查询包装器，用于查询条件
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_name", user.getUserName());
            // 检查数据库中是否存在该用户名
            User userDB = userMapper.selectOne(queryWrapper);
            if (userDB != null) {
                //身份校验
//                if (userDB.getRoles().equals(user.getRoles())){
                    Map<String, String> payloadtest = new HashMap<>();
                    payloadtest.put("id", userDB.getId().toString());
                    payloadtest.put("name", userDB.getUserName());
                    //返回token和身份
                    LoginVO loginVO = new LoginVO();
                    token = JWTUtils.getToken(payloadtest);
                    loginVO.setToken(token);
                    loginVO.setRole(userDB.getRoles());
                    loginVO.setUid(userDB.getId());
                    return CommonResult.success(loginVO, "登录成功");
//                }else {
//                    return CommonResult.failed("用户身份错误");
//                }
            }else {
                User newUser = User.builder()
                        .userName(user.getUserName())
                        .dycPassword(user.getDycPassword())
                        .roles(Constants.Role.NONE)
                        .nickName("用户"+CommonUtil.getRandomString(6, "0123456789"))
                        .authStatus(Constants.AuthStatus.UNAUTHENTICATED).build();
                save(newUser);
                Map<String, String> payload = new HashMap<>();
                payload.put("id", newUser.getId().toString());
                payload.put("name", newUser.getUserName());

                //返回token和身份
                LoginVO loginVO = new LoginVO();
                token = JWTUtils.getToken(payload);
                loginVO.setToken(token);
                loginVO.setRole(newUser.getRoles());
                loginVO.setUid(newUser.getId());
                return CommonResult.success(loginVO, "注册成功");
            }
        }


        try {
            // 创建一个查询包装器，用于查询条件
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_name", user.getUserName()); // 假设用户名字段为user_name
            // 检查数据库中是否存在该用户名
            User userDB = userMapper.selectOne(queryWrapper);
            if (userDB != null) {
                // 用户存在，校验密码
                if (userDB.getDycPassword().equals(user.getDycPassword())) {
                    // 校验动态码是否在有效期内
                    LocalDateTime dycPasswordTime = userDB.getLastModificationTime() != null
                            ? userDB.getLastModificationTime()
                            : LocalDateTime.now(); // 如果没有设置时间，则认为是当前时间生成的

                    LocalDateTime now = LocalDateTime.now();
                    Duration duration = Duration.between(dycPasswordTime, now);
                    long minutesBetween = duration.toMinutes();

                    if (minutesBetween < 1) {
                        //用户身份校验
//                        if (userDB.getRoles().equals(user.getRoles())){
                            // 动态码在有效期内，生成JWT令牌
                            Map<String, String> payload = new HashMap<>();
                            payload.put("id", userDB.getId().toString());
                            payload.put("name", userDB.getUserName());
                            //返回token和身份
                            LoginVO loginVO = new LoginVO();
                            token = JWTUtils.getToken(payload);
                            loginVO.setToken(token);
                            loginVO.setRole(userDB.getRoles());
                            loginVO.setUid(userDB.getId());
                            return CommonResult.success(loginVO, "登录成功");
//                        }else {
//                            return CommonResult.failed("用户身份错误");
//                        }
                    } else {
                        // 动态码已过期
                        throw new BaseException("动态码已过期，请重新获取");
                    }
                } else {
                    // 密码错误
                    throw new BaseException("短信验证码错误");
                }
            } else {
                // 用户不存在
                throw new BaseException("用户名不存在");
            }
        } catch (BaseException e) {
            // 已知异常处理
            return CommonResult.failed(e.getMessage());
        } catch (Exception e) {
            // 其他异常处理
            return CommonResult.failed("系统异常，请联系管理员");
        }
    }

    @Override
    public User selectById(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public User selectByUserName(String userName) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getUserName,userName);
        return getOne(queryWrapper);
    }

    @Override
    @Transactional
    public void authentication(User userdto) {
        log.info("SocialCode:"+userdto.getSocialCreditCode());

        String id = BaseUserInfo.get(UserInfoEnu.id.getCode());
        User userDB = getById(Long.valueOf(id));
        if (userDB == null){
            throw new BaseException("请重新登录后再进行认证");
        }
        //如果不是 未认证
        if (!userDB.getRoles().equals(Constants.Role.NONE)){
            throw new BaseException("该账号已完成身份认证");
        }
//        userDB.setTrueName(userdto.getTrueName());
//        userDB.setTelephone(userdto.getTelephone());
//        userDB.setIdentityNumber(userdto.getIdentityNumber());
//        userDB.setIdNumberPic(userdto.getIdNumberPic());
//        userDB.setIdNumberPic2(userdto.getIdNumberPic2());
//        userDB.setBusinessLicence(userdto.getBusinessLicence());

        String socialCreditCode = userdto.getSocialCreditCode();

        //判断统一社会信用代码是否格式正确
        if (!UnifiedCreditCodeUtil.checkUnifiedCreditCode(userdto.getSocialCreditCode())){
            throw new BaseException("统一社会信用代码格式错误");
        }
            //检查统一社会信用代码是否被使用过
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.lambda().eq(User::getSocialCreditCode,socialCreditCode);
        List<User> userDbList = list(userQueryWrapper);
        //如果当前统一社会信用代码未被使用过
        if (userDbList.isEmpty()){

            //登录手机号 作为 默认手机号码
            userDB.setTelephone(userDB.getUserName());
            userDB.setCompany(userdto.getCompany());
            userDB.setSocialCreditCode(userdto.getSocialCreditCode());
            userDB.setRegAddress(userdto.getRegAddress());

            userDB.setCerTime(LocalDateTime.now());

            userDB.setBusinessLicence(userdto.getBusinessLicence());

            userDB.setRoles(userdto.getRoles());

            //添加邀请人（禁止添加用户本人、禁止添加不存在的用户手机号）
            String inviteBy = userdto.getInviteBy();

            if (inviteBy != null && StringUtils.isNotBlank(inviteBy)) {
                User inviteUser = selectByUserName(inviteBy); //邀请人
                if (inviteUser != null) {
                    if (inviteUser.getUserName().equals(userDB.getUserName())){
                        throw new BaseException("禁止用户邀请自己");
                    }
                    userDB.setInviteBy(inviteUser.getUserName()); //邀请人
                    userDB.setInviteTime(LocalDateTime.now()); //邀请时间
                }else {
                    throw new BaseException("邀请人不存在");
                }
            }

            //实名认证状态设为：2（已实名）
            userDB.setAuthStatus(Constants.AuthStatus.AUTHENTICATED);
            userDB.setDriverLocation(userdto.getDriverLocation());
            if (userdto.getRoles() == 1) {
//                couponService.insert();
//                int couponNum = couponService.getCouponNum(userDB.getId());
//                userDB.setCouponNum(couponNum);
                String company = userDB.getCompany();
                List<User> users = userMapper.getUser(company);
                //已经认证过的公司不再增加优惠券 只返还有优惠券
                if (users.isEmpty()) {
                    log.info("公司首次认证添加优惠券");
                    couponDetService.insert();
                }else{
                    log.info("公司重复认证返还原有优惠券");
                    for (User user : users){
                        Integer couponNum = user.getCouponNum();
                        if (couponNum != null) {
                            log.info("更改已有优惠券状态");
                            UpdateWrapper<CouponDet> wrapper = new UpdateWrapper<>();
                            wrapper.lambda()
                                    .eq(CouponDet::getUid,user.getId())
                                    .set(CouponDet::getUid,userDB.getId());
                            couponDetService.update(wrapper);
                            break;
                        }
                    }
                }
                int couponDetNum = couponDetService.getCouponDetNum(userDB.getId());
                userDB.setCouponNum(couponDetNum);
            }
            userMapper.updateById(userDB);
        }else {
            throw new BaseException("当前统一社会信用代码已被绑定在其他账号");
        }

    }

    @Override
    @Transactional
    public void selectRole(Short role) {
        User user = userMapper.selectById(BaseUserInfo.get("id"));
        user.setRoles(role);
        updateById(user);

        if(Constants.Role.SHIPER.equals(role)){
            QueryWrapper<Shiper> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Shiper::getUid,user.getId());
            List<Shiper> shiperList = shiperService.list(wrapper);
            if(shiperList.isEmpty()){
                Shiper shiper = new Shiper();
                shiper.setUid(user.getId());
                shiperService.saveOrUpdate(shiper);
            }
        } else if (Constants.Role.DRIVER.equals(role)) {
            QueryWrapper<Driver> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Driver::getUid,user.getId());
            List<Driver> driverList = driverService.list(wrapper);
            if(driverList.isEmpty()){
                Driver driver = new Driver();
                driver.setUid(user.getId());
                driverService.saveOrUpdate(driver);
            }
        }
    }

    @Override
    public void addDelivery(Waybill waybill) {

        //更新货主发货量
        Long shiperId = waybill.getShiperId();
        User shiper = getById(shiperId);
        if (Objects.nonNull(shiper)){
            shiper.setTodayDelivery(shiper.getTodayDelivery() + 1);
            shiper.setTotalDelivery(shiper.getTotalDelivery() + 1);
            updateById(shiper);
        }
        //更新司机接单量
        Long driverId = waybill.getDriverId();
        User driver = getById(driverId);
        if (Objects.nonNull(driver)){
            driver.setTodayDelivery(driver.getTodayDelivery() + 1);
            driver.setTotalDelivery(driver.getTotalDelivery() + 1);
            updateById(driver);
        }

    }


    /**
     * 专线用户余额增加
     * @param id
     * @param income
     * @return
     */
    @Transactional
    @Override
    public BigDecimal addBalance(Long id, BigDecimal income) {
        User userDB = userMapper.selectByIdForUpdate(id); // 使用selectByIdForUpdate加悲观锁
        BigDecimal balanceAmt = new BigDecimal(0);
        if (userDB != null) {
            userDB.setBalanceAmt(userDB.getBalanceAmt().add(income));
            updateById(userDB);
            balanceAmt = userDB.getBalanceAmt();
        }
        return balanceAmt;
    }

    /**
     * 专线用户余额减少
     * @param id
     * @param income
     * @return
     */
    @Transactional
    @Override
    public BigDecimal reduceBalance(Long id, BigDecimal income) {
        User userDB = userMapper.selectByIdForUpdate(id); // 使用selectByIdForUpdate加悲观锁
        BigDecimal balanceAmt = new BigDecimal(0);
        if (userDB != null) {
            userDB.setBalanceAmt(userDB.getBalanceAmt().subtract(income));
            updateById(userDB);
            balanceAmt = userDB.getBalanceAmt();
        }
        return balanceAmt;
    }



    @Override
    public void addInviteIntegral(Waybill waybill, BigDecimal integral) {
        Long shiperId = waybill.getShiperId();
        User shiper = getById(shiperId);
        String inviteBy = shiper.getInviteBy();

        if (inviteBy != null && StringUtils.isNotBlank(inviteBy)) {
            User inviteUser = userMapper.selectByUserNameForUpdate(inviteBy);
            if (inviteUser != null) {
                inviteUser.setInviteIntegral(inviteUser.getInviteIntegral().add(integral));
                updateById(inviteUser);
            }
        }

    }

    @Override
    public User reduceInviteIntegral(Long uid, BigDecimal integral) {
        User userDB = userMapper.selectByIdForUpdate(uid); // 使用selectByIdForUpdate加悲观锁
        if (userDB != null) {
            userDB.setInviteIntegral(userDB.getInviteIntegral().subtract(integral));
            updateById(userDB);
        }
        return userDB;
    }


    @Override
    public void clear(Long uid) {
        User userDB = getById(uid);
        userDB.setIsDeleted(userDB.getId());
        updateById(userDB);
        System.out.println(userDB);
    }

    @Override
    public HashSet<String> getClear(Long uid) {
        //使用map保存不符合的条件
        HashSet<String> conditionSet = new HashSet<>();

        User user = selectById(uid);
        Short roles = user.getRoles();
        QueryWrapper<Waybill> waybillQueryWrapper = new QueryWrapper<>();
        //未结束的订单
        List<Short> filterList = Arrays.asList(Constants.WaybillStatus.AWAIT_QUOTE,
                Constants.WaybillStatus.DEPOSIT_PAID, Constants.WaybillStatus.AWAIT_SETTLEMENT);
        //判断用户身份
        if (Constants.Role.SHIPER.equals(roles)){
            waybillQueryWrapper.lambda()
                    .eq(Waybill::getShiperId, uid)
                    .in(Waybill::getWaybillStatus, filterList);
        }else if (Constants.Role.DRIVER.equals(roles)){
            waybillQueryWrapper.lambda()
                    .eq(Waybill::getDriverId, uid)
                    .in(Waybill::getWaybillStatus, filterList);
        }
        //如果用户已经认证过，才查询是否有未完成的订单
        if (!Constants.Role.NONE.equals(roles)){
            List<Waybill> waybills = wayBillService.list(waybillQueryWrapper);
            for (Waybill waybill : waybills) {
                Short w = waybill.getWaybillStatus();
                if (Constants.WaybillStatus.AWAIT_QUOTE.equals(w)){
                    conditionSet.add("账户存在报价中订单");
                }else if (Constants.WaybillStatus.DEPOSIT_PAID.equals(w) || Constants.WaybillStatus.AWAIT_SETTLEMENT.equals(w)){
                    conditionSet.add("账户存在未完成订单");
                }
            }
        }

        if (user.getBalanceAmt().compareTo(BigDecimal.ZERO) > 0){
            conditionSet.add("账户存在余额未提现");
        }
        return conditionSet;
    }

    @Override
    public void selectByP(int i) {
//        userMapper.select
    }

    @Override
    public void getCouponNum() {
        Long uid = Long.valueOf(BaseUserInfo.get(UserInfoEnu.id.getCode()));
        int couponNum = couponDetService.getCouponDetNum(uid);
        User user = userMapper.selectById(uid);
        user.setCouponNum(couponNum);
        userMapper.updateById(user);
    }

}
